using System;
using System.Collections.Generic;
using System.IO;

namespace WowAceUpdater
{
    // This is just a coding of the batch file helpers i have in C# to prevent
    // the security issues which might result from exevution of a batch file automatically
    internal class PseudoBatchFiles : IDisposable
    {
        #region Constants

        public const string WAU_FILE_LIST_NAME_NEW = ".wau";

        public const string WAU_FILE_LIST_NAME_OLD = "filelist.wau";

        #endregion

        #region Fields

//        private string _addonDirName;

        /// <summary>
        /// Complete reference to the addon dir
        /// </summary>
        private readonly DirectoryInfo _dir;

        private readonly List<DirectoryInfo> _files = new List<DirectoryInfo>(); // Sames as filelist

        private readonly TextWriter _t;

        #endregion

        #region Constructors

        public PseudoBatchFiles(string addonDir, TextWriter t)
        {
            try
            {
                _t = t;
                _dir = new DirectoryInfo(WowEnvironment.GetAddonDirectory(addonDir));

                string fl = GetFileListName(addonDir);
                if (fl != null)
                {
                    string[] subFolders = File.ReadAllLines(fl);

                    foreach (string s in subFolders)
                        if (s.Length > 0)
                            _files.Add(new DirectoryInfo(Path.Combine(_dir.FullName, s)));
                }
            }
#if DEBUG
            catch (Exception e)
            {
                _t.WriteLine("Error: {0} - {1}", addonDir, e.Message);
            }

#else
                catch (Exception) {}
#endif
        }

        #endregion

        #region Properties

        public List<DirectoryInfo> SubAddons
        {
            get { return _files; }
        }

        #endregion

/*
//         //
//         // FOR /F %%i IN (filelist) DO mkdir %%i 
//         //
//         public void CreateDirs() {
//             foreach (DirectoryInfo d in _files)
//             {
//                 d.Create();
//             }
//         }
 */

        #region IDisposable Members

        public void Dispose()
        {
        }

        #endregion

        public static string GetFileListName(string addonDir)
        {
            DirectoryInfo _dir = new DirectoryInfo(WowEnvironment.GetAddonDirectory(addonDir));

            string newFilelist = Path.Combine(_dir.FullName, WAU_FILE_LIST_NAME_NEW);
            if (File.Exists(newFilelist))
                return newFilelist;

            string oldFileList = Path.Combine(_dir.FullName, WAU_FILE_LIST_NAME_OLD);

            if (File.Exists(oldFileList))
                return oldFileList;

            return null;
        }

        // Trigger: is filelist.wau / it does have
        // the side effect of breaking the batch files unless i account for them

        //
        // dir /ad /b > filelist
        //
        //         public void MakeFileList() {           
        //             DirectoryInfo[] dirs = _dir.GetDirectories();
        //             
        //             _files.Initialize();
        // 
        //             foreach(DirectoryInfo di in dirs) {
        //                 _files[_files.Length] = di.Name;
        //             }
        //                 
        //             File.WriteAllLines(Path.Combine(_dir.FullName, WAU_FILE_LIST_NAME), _files);
        //         }

        //
        // if exist makefilelist.bat call makefilelist.bat
        // FOR /F %%i IN (filelist) DO move %%i ..
        //
        // They both return the list, so that you can mark those directories 
        public List<string> Install()
        {
            List<string> changed = new List<string>();
            foreach (DirectoryInfo di in _files)
            {
                try
                {
                    DirectoryInfo d = di;

                    string installName = ProcessInstallLocationName(_dir.Name, d.Name);

                    // Install Path, "..\SubAddonNmae"
                    DirectoryInfo i = new DirectoryInfo(Path.Combine(_dir.Parent.FullName, installName));

                    if (d.Name != i.Name)
                        d = new DirectoryInfo(Path.Combine(_dir.FullName, d.Name.Replace("@", "")));

                    if (!IsDirectoryProtected(i))
                    {
                        if (!i.Exists)
                            d.MoveTo(i.FullName);
                        else
                            FileSystem.DeleteDirectory(d.FullName);

                        FileInfo tag = new FileInfo(Path.Combine(i.FullName, "." + _dir.Name));

                        if (i.Exists && !tag.Exists)
                            if (!IsDirectoryProtected(i))
                            {
                                File.Copy(Path.Combine(_dir.FullName, _dir.Name + ".toc"),
                                          tag.FullName);
                            }

                        changed.Add(i.Name);
                    }
                }
#if DEBUG
                catch (Exception e)
                {
                    _t.WriteLine("Error: {0} - {1}", di, e.Message);
                }

#else
                catch (Exception) {}
#endif
            }

            return changed;
        }


        private static bool IsDirectoryProtected(DirectoryInfo i)
        {
            return FileSystem.IsDirectoryProtected(i);
        }

        [Obsolete]
        public void ReapplyTags()
        {
            DirectoryInfo d = null;
            foreach (DirectoryInfo di in _files)
            {
                try
                {
                    d = di;

                    string installName = ProcessInstallLocationName(_dir.Name, d.Name);

                    DirectoryInfo i = new DirectoryInfo(Path.Combine(_dir.Parent.FullName, installName));
                    if (d.Name != i.Name)
                        d = new DirectoryInfo(Path.Combine(_dir.FullName, d.Name.Substring(1)));

                    FileInfo tag = new FileInfo(Path.Combine(i.FullName, "." + _dir.Name));

                    if (i.Exists && !tag.Exists)
                        if (!IsDirectoryProtected(i) && _dir.Name != "Blizzard_Addons")
                        {
                            File.Copy(Path.Combine(_dir.FullName, _dir.Name + ".toc"),
                                      tag.FullName);
                        }
                }
#if DEBUG
                catch (Exception e)
                {
                    _t.WriteLine("Error: {0} - {1}", d, e.Message);
                }

#else
                catch (Exception e) { Program.LogDbg(e.ToString()); }
#endif
            }
        }

        //
        // FOR /F %%i IN (filelist) DO move ..\%%i .
        //
        public List<string> Uninstall(Object oLock)
        {
            DirectoryInfo d;
            List<string> changed = new List<string>();
            foreach (DirectoryInfo di in _files)
            {
                try
                {
                    d = di;

                    string installName = ProcessInstallLocationName(_dir.Name, d.Name);

                    DirectoryInfo i = new DirectoryInfo(Path.Combine(_dir.Parent.FullName, installName));
                    if (d.Name != i.Name)
                        d = new DirectoryInfo(Path.Combine(_dir.FullName, d.Name.Substring(1)));

                    if (i.Exists)
                        if (!FileSystem.IsDirectoryProtected(i.FullName))
                        {
                            changed.Add(i.Name);
                            if (!WowEnvironment.SupportsPackOperation(
                                     WowEnvironment.PackOperation.PACK, i.Name))
                            {
                                if (d.Exists) d.Delete(true);
                                i.MoveTo(d.FullName);
                            }
                            else
                                WowEnvironment.UninstallAddon(i.Name, _t, changed, oLock);
                        }
                }
                catch (Exception e)
                {
                    Program.LogDbg(e.ToString());
                }

            }

            return changed;
        }

        #region Private Methods

        private static string ProcessInstallLocationName(string addonName, string subaddonName)
        {
            string installName = subaddonName;

            return installName.Replace("@", addonName + "_");
        }

        #endregion
    }
}